package com.gitee.wsl.struct.router

import com.gitee.wsl.ext.any.ifNullValue
import com.gitee.wsl.struct.prioritizer.DefaultPrioritizer
import com.gitee.wsl.struct.prioritizer.InsertionOrderPrioritizer
import com.gitee.wsl.struct.prioritizer.Prioritizer
import com.gitee.wsl.collections.queue.ArrayQueue


interface Router<Context> {

    var notImplemented: CallHandler<Context>?

    //fun addRoute(url: String, priority: Int, handler: CallHandler?, vararg initParameter: Any)

    fun addRoute(url: String, method: Method = Method.GET, priority: Int, handler: CallHandler<Context>?, vararg initParameter: Any)

    fun removeRoute(url: String,method: Method = Method.GET)

    val prioritizedRoutes: ArrayQueue<UriResource<Context>>

}

open class BaseRouter<Context>(routePrioritize: Prioritizer<UriResource<Context>>) :
    Router<Context> {

    override var notImplemented: CallHandler<Context>?=null

    protected val mappings = routePrioritize.newMappingCollection()

    /*override fun addRoute(url: String, priority: Int, handler: CallHandler?, vararg initParameter: Any) {
        addRoute(url, Method.GET, priority, handler, *initParameter)
    }*/

    override fun addRoute(url: String, method: Method, priority: Int, handler: CallHandler<Context>?, vararg initParameter: Any) {
        if (handler != null) {
            mappings.add(
                UriResource(
                    url,
                    method,
                    priority + mappings.size,
                    handler,
                    *initParameter
                )
            )
        } else {
            mappings.add(UriResource(url, method, priority + mappings.size))
        }
    }

    override fun removeRoute(url: String, method: Method) {
        val uriToDelete: String = normalizeUri(url)
        val iter = mappings.iterator()
        while (iter.hasNext()) {
            val uriResource: UriResource<Context> = iter.next()
            if (uriToDelete == uriResource.baseUri && uriResource.method == method) {
                iter.remove()
                break
            }
        }
    }

    override val prioritizedRoutes: ArrayQueue<UriResource<Context>>
        get() = mappings

}

class ProvidedPriorityRouter<Context> : BaseRouter<Context>(DefaultPrioritizer()) {
    override fun addRoute(
        url: String,
        method: Method,
        priority: Int,
        handler: CallHandler<Context>?,
        vararg initParameter: Any
    ) {
        val resource = handler.ifNullValue(
            UriResource(url),
            UriResource(url, handler = handler, initParameter1 = initParameter)
        )
        resource.setPriority(priority)
        mappings.add(resource)
    }
}

class InsertionOrderRouter <Context>: BaseRouter<Context>(InsertionOrderPrioritizer())